package com.serverlite.framework.servlet.mapping;

import java.io.File;
import java.io.FileFilter;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class RouteMapping {

    private static Map<String,ClassMethod> urlMap = null;
    
    private static String rootPath = null;
    
    static{
        urlMap = new HashMap<String,ClassMethod>();
        rootPath = Thread.currentThread().getContextClassLoader().getResource("/").getPath();
    }
    
    public static void initMap(){
        Set<Class<?>> set = new HashSet<Class<?>>();
        
        scanClassFile(rootPath,set);
        
        filterController(set);

    }
    
    private static void scanClassFile(String path, Set<Class<?>> set){
        File dirs = new File(path);
        
        File[] dirfiles = dirs.listFiles(new FileFilter() {
            public boolean accept(File file) {  
                return (file.isDirectory()) || (file.getName().endsWith(".class"));
            }  
        });
        
        for(File file : dirfiles){
            if(file.isDirectory()){
                scanClassFile(file.getAbsolutePath(), set);
            } else {
                try {
                    String classPath = file.getAbsolutePath().substring(rootPath.length() - 1,file.getAbsolutePath().length() - 6).replace(File.separator, ".");
                    if(classPath.startsWith(".")){
                        classPath = classPath.substring(1, classPath.length());
                    }
                    set.add(Thread.currentThread().getContextClassLoader().loadClass(classPath));
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    private static void filterController(Set<Class<?>> set){
        for(Class<?> cla :set){
            if(cla.isAnnotationPresent(Controller.class)){
                Controller baseMapping = cla.getAnnotation(Controller.class);
                Method[] methods = cla.getMethods();
                for(Method m:methods){ 
                    if(m.isAnnotationPresent(RequestMapping.class)){
                        RequestMapping urlMapping = m.getAnnotation(RequestMapping.class);
                        ClassMethod cm = new ClassMethod();
                        cm.setClazz(cla);
                        cm.setMethod(m);
                        String url = baseMapping.value() + urlMapping.value();
                        if(urlMap.containsKey(url)){
                            throw new RuntimeException("RouteMapping exception URL " + url + " duplicate.");
                        } else {
                            urlMap.put(url, cm);
                        }
                    }
                }
            }
        }
    }
    
    public static Map<String,ClassMethod> getMap(){
        return urlMap;
    }
}
